package com.itheima.mp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.itheima.mp.domain.Address;
import com.itheima.mp.domain.User;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.enums.UserStatus;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.query.UserQuery;
import com.itheima.mp.service.IUserService;
import com.itheima.mp.vo.AddressVO;
import com.itheima.mp.vo.UserVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
//    @Override
//    @Transactional
//    public void deductionMoneyById01(Long id, Integer money) {
//        //1.
//        User user = this.getById(id); //执行，输出到控制台数据  <==      Total: 1
//        //2.
//        if(user == null || user.getStatus() == 2){
//            throw new RuntimeException("用户不存在或者被冻结!!!异常！！！");
//        }
//        //3.
//        if(user.getBalance()>=money){
//            user.setBalance(user.getBalance()-money);
//            // 需要更新用户信息到数据库,更新整个用户对象
////            this.updateById(user);
//
//            //4. 单独更新余额
////        baseMapper.deductionBalance(id,money); //调用mapper， 执行输出到控制台数据  <==      Updates: 1
////        或：
//            int remainBalance=user.getBalance()-money;
//            lambdaUpdate()
//                    .set(remainBalance == 0,User::getStatus,2)
//                    .set(User::getBalance,remainBalance)
//                    .eq(User::getId,id)
//                    .eq(User::getBalance,user.getBalance()) //防止并发更新, 判断当前用户余额是否为更新前的余额
//                    //乐观锁
//                    .update();
//        }
//        else{
//            throw new RuntimeException("余额不足!!!异常！！！");
//        }
//    }
@Override
@Transactional
public void deductionMoneyById01(Long id, Integer money) {
    User user = this.getById(id);
//    if (user == null || user.getStatus() == 2) {
    // 改进：添加枚举类型
    if (user == null || user.getStatus() == UserStatus.FROZEN) {
        throw new RuntimeException("用户不存在或者被冻结!!!异常！！！");
    }
    if (user.getBalance() >= money) {
        int originalBalance = user.getBalance();  // 保存原始余额
        int remainBalance = originalBalance - money;

        // 执行更新操作，使用乐观锁机制防止并发更新问题
        boolean updated = lambdaUpdate()
                // 条件设置：如果剩余余额为0，则将用户状态设为冻结(2)
                .set(remainBalance == 0, User::getStatus, 2)
                // 设置新的余额值
                .set(User::getBalance, remainBalance)
                // 精确定位要更新的用户记录
                .eq(User::getId, id)
                // 乐观锁关键：验证用户余额是否仍为原始值，防止并发修改
                .eq(User::getBalance, originalBalance)
                .update();

// 检查更新是否成功执行
        if (!updated) {
            // 如果没有记录被更新，说明乐观锁条件不满足，抛出异常
            throw new RuntimeException("更新失败，余额可能已被其他操作修改!");
        }

    }
}

    @Override
    public List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) {
        List<User> list = lambdaQuery().like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .ge(minBalance != null, User::getBalance, minBalance)
                .le(maxBalance != null, User::getBalance, maxBalance)
                .list();
        return list;
    }

    @Override
    public UserVO queryUserAndAddressById(Long id) {
        //1
        User user = getById(id);
        //    if (user == null || user.getStatus() == 2) {
        // 改进：添加枚举类型
        if(user ==  null || user.getStatus() == UserStatus.FROZEN){
            throw new RuntimeException("用户不存在或者被冻结");
        }
        //2.查询地址
        List<Address> address_list = Db.lambdaQuery(Address.class)
                .eq(Address::getUserId, id) //where
                .list();
        //3.组装数据
        UserVO userVOS = BeanUtil.copyProperties(user, UserVO.class);
        if(CollUtil.isNotEmpty(address_list)){
            userVOS.setAddressList(BeanUtil.copyToList(address_list, AddressVO.class));
        }
        System.out.println("测试成功:");
        System.out.println(userVOS.getAddressList());
        return userVOS;
    }

    @Override
    public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
        // 1.查询用户
        List<User> users = listByIds(ids);
        if (CollUtil.isEmpty(users)) {
            return Collections.emptyList();
        }
// 2.查询地址
// 2.1.获取用户id集合
        List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
// 2.2.根据用户id查询地址
        List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
// 2.3.转换地址VO
        List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
// 2.4.用户地址集合分组处理，相同用户的放入一个集合（组）中
        Map<Long, List<AddressVO>> addressMap11 = new HashMap<>(0);
        if(CollUtil.isNotEmpty(addressVOList)) {
            addressMap11 = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        }

// 3.转换VO返回
        List<UserVO> list = new ArrayList<>(users.size());
        for (User user : users) {
            // 3.1.转换User的PO为VO
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            list.add(vo);
            // 3.2.转换地址VO
            vo.setAddressList(addressMap11.get(user.getId()));
        }
        return list;
    }

    @Override
    public PageDTO<UserVO> queryUserPage(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();
// 1.构建分页条件
// 1.1.分页条件
        Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
// 1.2.排序条件
        if(StrUtil.isNotBlank(query.getSortBy())){
            // 不为空
            page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc() != null ? query.getIsAsc() : false));
        }else{
            // 为空，默认按照更新时间排序
            page.addOrder(new OrderItem("update_time", false));
        }

// 2.分页查询
        Page<User> p = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .page(page);
// 3.封装VO结果
        PageDTO<UserVO> dd = new PageDTO<>();
        //3.1
        dd.setTotal(p.getTotal());
        //3.2
        dd.setPages(p.getPages()); //要Long
        //3.3
        List<User> records = p.getRecords();
        if(CollUtil.isEmpty( records)){
            dd.setList(Collections.emptyList());
            return dd;
        }
        //3.4
        List<UserVO> userVOS = BeanUtil.copyToList(records, UserVO.class);
        dd.setList(userVOS);
        //4.封装VO结果
        return dd;
    }
}
